<!--
 * @Description:新建BGP
 * @Author: 0001101008/HuYuxi
 * @Date: 2021-08-30 14:27:29
 * @LastEditTime: 2021-11-17 13:15:44
 * @LastEditors: 0001101008/HuYuxi
-->
<template>
  <div class="page-content" style="padding: 0">
    <!-- 新建BGP -->
    <el-dialog
      title="BGP配置"
      :close-on-click-modal="false"
      width="500px"
      :visible.sync="dialogStatus"
      @close="cancel"
    >
      <el-tabs
        v-model="activeName"
        type="card"
        :closable="policyTab.length > 1 ? true : false"
        addable
        @tab-add="tabAdd"
        @tab-remove="tabRemove"
      >
        <!-- 基本信息 -->
        <el-tab-pane label="基本信息" name="base">
          <el-form
            ref="baseForm"
            :model="bgpForms"
            :rules="rules"
            label-width="100px"
            label-position="right"
          >
            <!-- 租户 -->
            <el-form-item label="租户名称" prop="dgId">
              <el-select v-model="bgpForms.dgId" style="width:100%;">
                <el-option
                  v-for="(item, index) in tenantList"
                  :key="index"
                  :value="item.value"
                  :label="item.label"
                ></el-option>
              </el-select>
            </el-form-item>
            <!-- IPv6 vrf名称 -->
            <el-form-item
              label="VRF名称"
              prop="instanceName"
              :rules="{required: true, message: '请检查必填项！', trigger: 'change'}"
              v-if="ne.extAttrs.IPAddressMode === 'V6'"
            >
              <el-select v-model="bgpForms.instanceName" style="width:100%;">
                <el-option
                  v-for="(item, index) in vrfList"
                  :key="index"
                  :value="item.instanceName"
                  :label="item.userlabel"
                ></el-option>
              </el-select>
            </el-form-item>
            <!-- 本端AS -->
            <el-form-item label="本端AS" prop="localAs">
              <el-input v-model="bgpForms.localAs" placeholder="本端AS" />
            </el-form-item>
            <!-- 对端AS -->
            <el-form-item label="对端AS" prop="remoteAs">
              <el-input v-model="bgpForms.remoteAs" placeholder="对端AS" />
            </el-form-item>
            <!-- 对端IP -->
            <el-form-item label="对端IP" prop="remoteIp">
              <el-input v-model="bgpForms.remoteIp" placeholder="对端IP" />
            </el-form-item>
            <!-- RouterId -->
            <el-form-item label="RouterId" prop="routerId">
              <el-input v-model="bgpForms.routerId" placeholder="RouterId: IPv4/IPv6" />
            </el-form-item>
            <!-- KeepAlive -->
            <el-form-item
              label="KeepAlive"
              prop="keepAliveTime"
              :rules="{validator: validKeepAliveTime, trigger: ['blur', 'change']}"
            >
              <el-input-number v-model="bgpForms.keepAliveTime" label="keepAliveTime"></el-input-number>
              <span style="margin-left:10px">秒</span>
            </el-form-item>
            <!-- HoldTime -->
            <el-form-item
              label="HoldTime"
              prop="holdTime"
              :rules="{validator: validHoldtime, trigger: ['blur', 'change']}"
            >
              <el-input-number v-model="bgpForms.holdTime" label="HoldTime"></el-input-number>
              <span style="margin-left:10px">秒</span>
            </el-form-item>
            <!-- 认证方式 -->
            <el-form-item label="认证方式" prop="auth">
              <el-select v-model="bgpForms.auth" style="width:100%;">
                <el-option
                  v-for="(item, index) in authList"
                  :key="index"
                  :value="item.value"
                  :label="item.label"
                ></el-option>
              </el-select>
            </el-form-item>
            <!-- 密码 -->
            <el-form-item
              label="密码"
              prop="password"
              v-if="bgpForms.auth === 'md5'"
              maxlength="80"
              :rules="[
              {required: true, message: '请检查必填项！', trigger: 'blur'},
                  { pattern: /^[0-9a-zA-Z~!@#$%^&*]+$/, message: '格式不正确' ,trigger: 'blur'}
                ]"
            >
              <el-input v-model="bgpForms.password" placeholder="请输入密码" show-password />
            </el-form-item>
          </el-form>
        </el-tab-pane>
        <!-- 路由通告 -->
        <el-tab-pane label="路由通告" name="notice">
          <el-form
            ref="noticeForm"
            :model="bgpForms"
            :rules="rules"
            label-width="140px"
            label-position="right"
          >
            <!-- NetWork通告重分布 -->
            <el-form-item label="NetWork通告重分布" prop="network">
              <el-input v-model="bgpForms.network.ip" placeholder="IPv4/IPv6" class="network-ip" />
              <el-input v-model.number="bgpForms.network.mask" placeholder="掩码" style="width:70px" />
            </el-form-item>
            <!-- 默认路由 直连路由 静态路由 -->
            <el-form-item label prop="routerType">
              <el-checkbox-group v-model="bgpForms.routerType">
                <el-checkbox label="defaultOriginate">默认路由</el-checkbox>
                <el-checkbox label="connected">直连路由</el-checkbox>
                <el-checkbox label="staticed">静态路由</el-checkbox>
              </el-checkbox-group>
            </el-form-item>
          </el-form>
        </el-tab-pane>
        <!-- 路由策略 -->
        <el-tab-pane
          :label="item.label"
          :name="item.name"
          v-for="(item, index) in policyTab"
          :key="index"
        >
          <el-form
            ref="policyForm"
            :id="'policyForm' + index"
            :model="policyTab[index].content"
            label-width="80px"
            label-position="right"
          >
            <el-alert title="如要配置路由策略，请至少选择一个前缀列表、保证类型有值，否则可能导致BGP配置失败" type="warning" show-icon></el-alert>
            <el-divider>发布方向</el-divider>
            <!-- 前缀列表 -->
            <el-form-item label="前缀列表" prop="frontPre">
              <el-select v-model="item.content.frontPre" multiple style="width:100%;">
                <el-option
                  v-for="(item, index) in preList"
                  :key="index"
                  :value="item.name"
                  :label="item.name"
                ></el-option>
              </el-select>
            </el-form-item>
            <!-- 类型 -->
            <el-form-item label="类型" prop="frontType">
              <el-select v-model="item.content.frontType" style="width:100%;">
                <el-option :value="true" label="白名单"></el-option>
                <el-option :value="false" label="黑名单"></el-option>
              </el-select>
            </el-form-item>
            <!-- med -->
            <el-form-item label="med" :prop="'med'">
              <el-input-number v-model="item.content.med" :min="0" :max="4294967295" label="med"></el-input-number>
            </el-form-item>
            <!-- 团体 -->
            <el-form-item label="团体" prop="community">
              <el-input
                v-model.number="item.content.community.a"
                placeholder="范围为1-4294967295"
                class="ip-community"
              />
              <span>:</span>
              <el-input
                v-model.number="item.content.community.b"
                placeholder="范围为1-4294967295"
                class="ip-community"
              />
            </el-form-item>
            <el-form-item
              label="AS Path"
              prop="asPass"
              :rules="{validator: validAsPath, trigger: 'blur'}"
            >
              <el-input v-model.trim="item.content.asPass" placeholder="格式为：100,100,...，最多写10个" />
            </el-form-item>
            <el-divider>接收方向</el-divider>
            <!-- 前缀列表 -->
            <el-form-item label="前缀列表" prop="afterPre">
              <el-select v-model="item.content.afterPre" multiple style="width:100%;">
                <el-option
                  v-for="(item, index) in preList"
                  :key="index"
                  :value="item.name"
                  :label="item.name"
                ></el-option>
              </el-select>
            </el-form-item>
            <!-- 类型 -->
            <el-form-item label="类型" prop="afterType">
              <el-select v-model="item.content.afterType" style="width:100%;">
                <el-option :value="true" label="白名单"></el-option>
                <el-option :value="false" label="黑名单"></el-option>
              </el-select>
            </el-form-item>
          </el-form>
        </el-tab-pane>
      </el-tabs>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancel">取消</el-button>
        <el-button type="primary" @click="onSubmit">确认</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  props: ['dialogStatus', 'tenantList', 'ne', 'vrfList'],
  components: {},
  data () {
    let validateAS = (rule, value, cb) => {
      if (!value) {
        return cb(new Error('请检查必填项！'));
      } else {
        let reg = /^[0-9]+$/g;
        if (!reg.test(value)) {
          return cb(new Error('请输入合理的AS号'));
        } else {
          if (value < 1 || value > 4294967295) {
            return cb(new Error('格式不正确，范围1-4294967295'));
          } else {
            return cb();
          }
        }
      }
    };
    return {
      activeName: 'base',
      // 行内数据
      lineRow: {},
      bgpForms: {
        localAs: null,
        remoteAs: null,
        remoteIp: null,
        routerId: null,
        keepAliveTime: 60,
        holdTime: 180,
        network: {
          ip: null,
          mask: 32
        },
        routerType: [],
        frontPre: [],
        afterPre: [],
        policyList: [],
        tenantList: [],
        instanceName: null
      },
      rules: {
        dgId: [{ required: true, message: '请检查必填项！', trigger: 'change' }],
        localAs: [{ required: true, validator: validateAS, trigger: 'blur' }],
        remoteAs: [{ required: true, validator: validateAS, trigger: 'blur' }]
      },
      policyTab: [{
        name: 'policy',
        label: '路由策略',
        content: {
          frontPre: [],
          frontType: null,
          med: null,
          community: {
            a: null,
            b: null
          },
          asPass: null,
          afterPre: [],
          afterType: null,
        }
      }],
      tabIndex: 1,
      authList: [
        { label: '无', value: 'none' },
        { label: 'MD5', value: 'md5' }
      ],
      preList: [],
      page: {
        page: 1,
        pageSize: 15,
        total: 0
      }
    };
  },
  watch: {},
  mounted () {
    let _this = this;
    _this.$nextTick(() => {
      _this.getPreList();
    });
  },
  methods: {
    // keepAliveTime验证
    validKeepAliveTime (rule, value, cb) {
      if (value < 0 || value > 65535) {
        return cb(new Error('范围是：0-65535'));
      } else {
        if (value > this.bgpForms.holdTime) {
          return cb(new Error('holdTime定时时间大于等于keepAliveTime定时时间'));
        } else {
          return cb();
        }
      }
    },
    // HoldTime验证
    validHoldtime (rule, value, cb) {
      if (value < 0 || value > 65535) {
        return cb(new Error('范围是：0-65535'));
      } else {
        if (value < this.bgpForms.keepAliveTime) {
          return cb(new Error('holdTime定时时间大于等于keepAliveTime定时时间'));
        } else {
          return cb();
        }
      }
    },
    // 数组去除空值、undefined、null
    trimNull (arr) {
      for (let i = 0; i < arr.length; i++) {
        if (arr[i] === '' || arr[i] === 'undefined' || arr[i] === null) {
          arr.splice(i, 1);
          i = i - 1;
        }
      }
      return arr;
    },
    // 验证as Path
    validAsPath (rule, value, cb) {
      if (value) {
        if (value.indexOf(',') === -1) {
          return cb(new Error('格式不正确'));
        } else {
          let arr = this.trimNull(value.split(','));
          let flag = false;
          let reg = /^[0-9]+$/;
          let sum = 0;
          if (arr.length > 10) {
            return cb(new Error('格式不正确，最多可以写10个'));
          } else {
            for (let i = 0; i < arr.length; i++) {
              if (!reg.test(arr[i])) {
                flag = true;
                break;
              } else {
                sum = sum + Number(arr[i].length);
              }
            }
          }
          if (flag) {
            return cb(new Error('格式不正确'));
          } else {
            if (sum > 100) {
              return cb(new Error('格式不正确，值之和不可以超过100'));
            } else {
              return cb();
            }
          }
        }
      }

    },
    // 新增路由策略的tab
    tabAdd () {
      let _this = this;
      let count = ++_this.tabIndex;
      let newTabName = 'policy' + count;
      let newTabLabel = '路由策略' + count;
      _this.policyTab.push({
        name: newTabName,
        label: newTabLabel,
        content: {
          frontPre: [],
          frontType: null,
          med: null,
          community: {
            a: null,
            b: null
          },
          asPass: null,
          afterType: null,
          afterPre: []
        }
      });
      _this.activeName = newTabName;
    },
    // 删除路由策略的tab
    tabRemove (targetName) {
      let _this = this;
      let tabs = _this.policyTab;
      let activeName = _this.activeName;
      if (tabs.length > 1) {
        if (targetName === activeName) {
          tabs.map((item, index) => {
            if (targetName === item.name) {
              let nextTab = tabs[index + 1] || tabs[index - 1];
              if (nextTab) {
                activeName = nextTab.name;
              }
            }
          });
        }
        _this.activeName = activeName;
        _this.policyTab = tabs.filter(tab => tab.name !== targetName);
        // 拿到最后一个tabs，方便取出当前是第几个,路由的展示问题处理
        let lastTab = _this.policyTab[_this.policyTab.length - 1];
        let index = lastTab.label.slice(-1);
        _this.tabIndex = index === '略' ? 1 : index;
      } else {
        return;
      }
    },
    // 取消
    cancel () {
      let _this = this;
      _this.clearData();
      _this.$emit('handleDialog', false);
    },
    // 清空表单数据
    clearData () {
      let _this = this;
      _this.bgpForms = {
        localAs: null,
        remoteAs: null,
        remoteIp: null,
        routerId: null,
        keepAliveTime: 60,
        holdTime: 180,
        network: {
          ip: null,
          mask: 32
        },
        routerType: [],
      };
      _this.policyTab = [{
        name: 'policy',
        label: '路由策略',
        content: {
          frontPre: [],
          frontType: null,
          med: null,
          community: {
            a: null,
            b: null
          },
          asPass: null,
          afterType: null,
          afterPre: []
        }
      }];
      _this.activeName = 'base';
    },
    // 获取前缀列表
    getPreList () {
      let _this = this;
      let params = {
        neId: _this.ne.id,
        limit: -1,
        offset: 0
      };
      _this.$http.post({
        url: '/api/sdwan/prefixlist/query',
        data: params
      }).then(res => {
        let { status, resultBody } = res;
        if (status === '0') {
          _this.page.total = resultBody.count;
          _this.preList = resultBody.objects;
        }
      });
    },
    // 提交，创建BGP
    onSubmit () {
      let _this = this;
      let p1 = new Promise(resolve => {
        _this.$refs['baseForm'].validate(valid => {
          resolve(valid);
        });
      });
      let p2 = new Promise((resolve) => {
        _this.$refs['noticeForm'].validate(valid => {
          resolve(valid);
        });
      });
      let p3 = [];
      for (let i = 0; i < _this.policyTab.length; i++) {
        let formDom = document.getElementById('policyForm' + i);
        let errorDom = formDom.querySelectorAll('.el-form-item__error');
        if (errorDom.length > 0) {
          p3.push(true);
        }
      }
      let flag = true;
      for (let i = 0; i < p3.length; i++) {
        if (p3.indexOf(true) > -1) {
          flag = false;
        }
      }
      Promise.all([p1, p2, flag]).then((valid) => {
        if (valid.indexOf(false) === -1) {
          let tabs = _this.policyTab;
          // 接收方向
          let ingressItems = [];
          // 发布方向
          let egressItems = [];
          tabs.map(item => {
            let asPass = [];
            if (item.content.asPass) {
              let list = this.trimNull(item.content.asPass.split(','));
              asPass = list.map(item => {
                return Number(item);
              });
            } else {
              asPass = [];
            }
            let o = {
              permit: item.content.frontType,
              med: item.content.med,
              asPass: asPass,
              community: item.content.community.a ? item.content.community.a + ':' + item.content.community.b : '',
              prefixListNames: []
            };
            if (item.content.frontPre.length > 0) {
              o.prefixListNames = item.content.frontPre;
            }
            egressItems.push(o);
            let after = {
              permit: item.content.afterType,
              prefixListNames: []
            };
            if (item.content.afterPre.length > 0) {
              after.prefixListNames = item.content.afterPre;
            }
            ingressItems.push(after);
          });
          let params = {
            neId: _this.ne.id,
            dgId: _this.ne.dgId,
            siteId: _this.ne.extAttrs.siteId,
            localAs: _this.bgpForms.localAs,
            remoteAs: _this.bgpForms.remoteAs,
            remoteIp: _this.bgpForms.remoteIp,
            routerId: _this.bgpForms.routerId,
            keepAliveTime: _this.bgpForms.keepAliveTime,
            holdTime: _this.bgpForms.holdTime,
            password: _this.bgpForms.password,
            network: _this.bgpForms.network.ip ? _this.bgpForms.network.ip + '/' + _this.bgpForms.network.mask : null,
            defaultOriginate: _this.bgpForms.routerType.indexOf('defaultOriginate') > -1 ? true : false,
            connected: _this.bgpForms.routerType.indexOf('connected') > -1 ? true : false,
            staticed: _this.bgpForms.routerType.indexOf('staticed') > -1 ? true : false,
            ingressItems: ingressItems,
            egressItems: egressItems,
            vrfId: _this.bgpForms.dgId,
            instanceName: _this.ne.extAttrs.IPAddressMode === 'V6' ? _this.bgpForms.instanceName : null
          };
          _this.$http.post({
            url: '/api/sdwan/bgp/create',
            data: params
          }).then(res => {
            let { status } = res;
            if (status === '0') {
              _this.$message.success('创建成功！');
              _this.cancel();
              _this.$parent.refresh();
            }
          });
        } else {
          _this.$message.error('请检查必填项！');
          // valid[] 第一个是base信息的0 第二个是路由通告的1 从第三个开始就都是路由策略的2
          if (valid.indexOf(false) === 0) {
            _this.activeName = 'base';
          } else if (valid.indexOf(false) === 1) {
            _this.activeName = 'notice';
          } else {
            // 找到第一个的位置即可
            let index = valid.findIndex(item => item === false);
            _this.activeName = index === 2 ? 'policy' : 'policy' + (index - 2);
          }
        }
      });
    }
  }
};
</script>

<style lang='scss' scoped>
.page-content {
  width: 100%;
  height: 100%;
  ::v-deep .el-dialog__body {
    padding: 0 20px 0 !important;
  }
  ::v-deep .el-dialog__header {
    border: none !important;
  }
  .network-ip {
    width: 246px;
  }
  .ip-mask {
    width: 60px;
  }
  .ip-gt {
    width: 60px;
  }
  .ip-lt {
    width: 60px;
  }
  .ip-community {
    width: 184px;
  }
}
::v-deep .el-tabs {
  margin-bottom: 20px;
}
::v-deep .el-tabs__new-tab {
  background-color: #67c23a;
  border-color: #e1f3d8;
  color: #e1f3d8;
}
@media only screen and (max-width: $device-phone) {
  .page-content {
    .network-ip {
      width: 140px;
    }
    .ip-mask {
      width: 102px;
    }
    .ip-gt {
      width: 97px;
    }
    .ip-lt {
      width: 97px;
      margin-left: 80px;
    }
    .ip-community {
      width: 126px;
    }
  }
}
.item-box {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
}
</style>